package DBIx::Class::Component::DataValidator::DBMS::mysql;

use strict;
use Class::C3;

use base qw/
    DBIx::Class::Component::DataValidator::DBMS
/;

use DateTime;
use DateTime::Format::Flexible;
use DateTime::Format::MySQL;

our $VERSION = '0.05';

=head1 NAME

DBIx::Class::Component::DataValidator::DBMS::mysql - validation for MySQL datatypes

=head1 DESCRIPTION

Adds mysql specific datatypes.

=cut


=head1 DATATYPE VALIDATORS

=head2 date

A date representative (YYYY-MM-DD)

=head2 datetime

A datetime representative (YYYY-MM-DD HH:MM:SS)

=head2 time

A datetime representative (HH:MM:SS)

=head2 enum

An enum value out of a set of allowed values

=head2 set

Multiple set values out of a set of allowed values

=cut

__PACKAGE__->add_datatype_validators( {
    date => sub {
        my ( $dv, $col_ref, $value ) = @_;
        
        # check null
        return 0 if ! defined $value && ! $col_ref  ->{ is_nullable };
        
        # parse input
        my $dt;
        eval {
            $dt = DateTime::Format::Flexible->parse_datetime( $value );
        };
        return 0 if $@ || ! $dt;
        
        # ok, set formatted ..
        $dv->get_filtered_data->{ $dv->get_current_constraint_field } = $dt->strftime( '%Y-%m-%d' );
        return 1;
    },
    datetime => sub {
        my ( $dv, $col_ref, $value ) = @_;
        
        # check null
        return 0 if ! defined $value && ! $col_ref  ->{ is_nullable };
        
        # parse input
        my $dt;
        eval {
            $dt = DateTime::Format::Flexible->parse_datetime( $value );
        };
        return 0 if $@ || ! $dt;
        
        # ok, set formatted ..
        $dv->get_filtered_data->{ $dv->get_current_constraint_field } = DateTime::Format::MySQL->format_datetime( $dt );
        return 1;
    },
    
    
    time => sub {
        my ( $dv, $col_ref, $value ) = @_;
        
        # check null
        return 0 if ! defined $value && ! $col_ref  ->{ is_nullable };
        
        # parse input
        my $dt;
        eval {
            $dt = DateTime::Format::Flexible->parse_datetime( $value );
        };
        return 0 if $@ || ! $dt;
        
        # ok, set formatted ..
        $dv->get_filtered_data->{ $dv->get_current_constraint_field } = $dt->strftime( '%H:%M:%S' );
        return 1;
    },
    
    enum => sub {
        my ( $dv, $col_ref, $value ) = @_;
        
        # check null..
        return 0 if ! defined $value && ! $col_ref->{ is_nullable };
        
        # get allowed values
        my %allowed = map { ( $_ => 1 ) } @{ $col_ref->{ extra }->{ list } };
        
        # check wheter allowed
        return $allowed{ $value };
    },
    
    set => sub {
        my ( $dv, $col_ref, $value ) = @_;
        
        # check null..
        return 0 if ! defined $value && ! $col_ref->{ is_nullable };
        
        # get allowed values
        my %allowed = map { ( $_ => 1 ) } @{ $col_ref->{ extra }->{ list } };
        
        # split input values
        my @values  = split( /\s*,\s*/, $value );
        
        # check all values against set
        foreach my $check( @values ) {
            return 0 unless $allowed{ $check };
        }
        
        # all ok
        return 1;
    },
    
    # todo ??
    #   geometry
    #   point 
    #   linestring 
    #   polygon 
    #   multipoint 
    #   multistring 
    #   multipolygon 
    #   geometrycollection 
} );



1;
